from django.http import JsonResponse
from django.shortcuts import render_to_response, render
from django.views.decorators.csrf import ensure_csrf_cookie
from .models import *
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.template import RequestContext
from django.db.models import Q
from .IpInfo import *
from django.core.cache import cache
from django.views.decorators.cache import cache_page
from django.db import transaction
from .templatetags.xBlog_filter import gravatar, get_visitor_url
from .TimezoneUtils import utc2local, local2utc
from django.http import HttpResponseForbidden, Http404
from django.utils import timezone


@ensure_csrf_cookie
# @cache_page(60 * 5)
def home(request):
    if request.method == 'GET':
        if 'keyword' in request.GET:
            keyword = request.GET.get('keyword')
            posts = Article.objects.filter(
                Q(title__icontains=keyword) | Q(content__icontains=keyword)).prefetch_related()

            catagories = Catagory.objects.filter(catagory_name__iexact=keyword).prefetch_related()
            if catagories:
                posts = set(posts)
                for catagory in catagories:
                    posts.update(catagory.article_set.all())
                posts = list(posts)

            tags = Tag.objects.filter(tag_name__iexact=keyword).prefetch_related()
            if tags:
                posts = set(posts)
                for tag in tags:
                    posts.update(tag.article_set.all())
                posts = list(posts)

            posts = sorted(posts, key=lambda x: x.date_time, reverse=True)
            result_num = len(posts)

        else:
            posts = Article.objects.all().prefetch_related()
            keyword = None
            result_num = 0

        page = request.GET.get('page')

        paginator = Paginator(posts, 8)
        # records = ReadRecord.objects.all().order_by('-date_time')[:5]
        # comments = Comment.objects.all().order_by('-submit_time')
        # latest_comments = comments[:5]
        try:
            post_list = paginator.page(page)
        except PageNotAnInteger:
            post_list = paginator.page(1)
        except EmptyPage:
            post_list = paginator.page(paginator.num_pages)

        return render_to_response('xBlog/articles.html',
                                  {'post_list': post_list, 'keyword': keyword,
                                   'result_num': result_num},
                                  context_instance=RequestContext(request))
    else:
        raise Http404


@ensure_csrf_cookie
@transaction.atomic
# @cache_page(60 * 5)
def get_detail(request, article_id):
    ip = request.META['HTTP_X_FORWARDED_FOR'] if 'HTTP_X_FORWARDED_FOR' in request.META else request.META[
        'REMOTE_ADDR']

    visitor = Visitor.get_visitor(ip)

    try:
        article = Article.objects.prefetch_related().select_related().get(pk=article_id)
        article.visit()

        article_suggest = Article.objects.filter(Q(catagory=article.catagory) & ~Q(pk=article.id)).order_by('?')[:4]

        previous_articles = Article.objects.filter(pk__lt=article_id).order_by('-pk')
        next_articles = Article.objects.filter(pk__gt=article_id).order_by('pk')

        p_article = previous_articles[0] if len(previous_articles) else None
        n_article = next_articles[0] if len(next_articles) else None

        try:
            record = ReadRecord.objects.get(Q(article=article) & Q(visitor=visitor))
        except ReadRecord.DoesNotExist:
            ReadRecord.objects.create(article=article, visitor=visitor)
        else:
            record.date_time = timezone.now()
            record.save()

        records = article.readrecord_set.all().order_by('-date_time')[:4]

    except Article.DoesNotExist:
        raise Http404
    return render_to_response('xBlog/detail.html',
                              {'article': article, 'suggest': article_suggest, 'previous': p_article, 'next': n_article,
                               'records': records}, context_instance=RequestContext(request))


@ensure_csrf_cookie
def get_tag_list(request, tag_name):
    try:
        tag = Tag.objects.get(tag_name=tag_name)
    except Article.DoesNotExist:
        raise Http404
    posts = tag.article_set.all()
    paginator = Paginator(posts, 8)
    page = request.GET.get('page')
    try:
        post_list = paginator.page(page)
    except PageNotAnInteger:
        post_list = paginator.page(1)
    except EmptyPage:
        post_list = paginator.page(paginator.num_pages)
    return render_to_response('xBlog/articles.html', {'post_list': post_list}, context_instance=RequestContext(request))


@ensure_csrf_cookie
def get_archive_list(request, archive_name):
    try:
        archive = Archive.objects.prefetch_related().get(archive_name=archive_name)
    except Article.DoesNotExist:
        raise Http404
    posts = archive.article_set.all()
    paginator = Paginator(posts, 8)
    page = request.GET.get('page')
    try:
        post_list = paginator.page(page)
    except PageNotAnInteger:
        post_list = paginator.page(1)
    except EmptyPage:
        post_list = paginator.page(paginator.num_pages)
    return render_to_response('xBlog/articles.html', {'post_list': post_list}, context_instance=RequestContext(request))


@ensure_csrf_cookie
def get_catagory_list(request, catagory_name):
    try:
        catagory = Catagory.objects.prefetch_related().get(catagory_name=catagory_name)
    except Article.DoesNotExist:
        raise Http404
    posts = catagory.article_set.all()
    paginator = Paginator(posts, 8)
    page = request.GET.get('page')
    try:
        post_list = paginator.page(page)
    except PageNotAnInteger:
        post_list = paginator.page(1)
    except EmptyPage:
        post_list = paginator.page(paginator.num_pages)
    return render_to_response('xBlog/articles.html', {'post_list': post_list}, context_instance=RequestContext(request))


def alipay(request):
    return render(request, 'xBlog/alipay.html', context_instance=RequestContext(request))


@cache_page(60 * 5)
def resume(request):
    return render(request, 'xBlog/resume.html', context_instance=RequestContext(request))


@transaction.atomic
def submit_comment(request, article_id):
    if request.method == 'POST':
        ip = request.META['HTTP_X_FORWARDED_FOR'] if 'HTTP_X_FORWARDED_FOR' in request.META else request.META[
            'REMOTE_ADDR']
        try:
            visitor = Visitor.get_visitor(ip, abort403=True)
        except Visitor.DoesNotExist:
            return HttpResponseForbidden()

        visitor.nickname = request.POST.get('nickname') or visitor.nickname
        visitor.email = request.POST.get('email') or visitor.email
        visitor.url = request.POST.get('url') or visitor.url
        visitor.save()

        content = request.POST.get('content')
        reply_to_who_id = request.POST.get('reply_to_who_id')

        try:
            article = Article.objects.get(pk=article_id)
        except Article.DoesNotExist:
            raise Http404

        comment = Comment(article_id=article, visitor=visitor, content=content)
        reply_to = comment.submit(reply_to_who_id)

        result = dict()
        result['author'] = visitor.nickname + ip_protect(visitor.ip_address) + '[' + visitor.city + ']'
        result['id'] = comment.id
        result['author_id'] = comment.visitor.id
        result['url'] = get_visitor_url(visitor)
        result['avatar'] = gravatar(visitor.email)
        result['content'] = content
        result['submit_time'] = utc2local(comment.submit_time).strftime('%Y-%m-%d %H:%M')

        if comment.reply_to_who_id:
            result['reply_to_id'] = comment.reply_to_who_id.comment_id
            result['reply_to'] = reply_to

        return JsonResponse(result)
    else:
        raise Http404


def today_visitors(request):
    if request.method == 'POST':
        date = datetime.datetime.now().strftime('%Y/%m/%d')
        date_begin = local2utc(datetime.datetime.strptime(date, '%Y/%m/%d'))
        date_end = local2utc(datetime.datetime.strptime(date + ' 23:59:59', '%Y/%m/%d %H:%M:%S'))
        vistiors = Visitor.objects.filter(Q(date_time__lte=date_end) & Q(date_time__gt=date_begin)).order_by(
            '-date_time')

        data = []
        for v in vistiors:
            data.append({'nickname': v.nickname + ip_protect(v.ip_address) + '[' + v.city + ']',
                         'date_time': utc2local(v.date_time).strftime('%H:%M')})

        return JsonResponse({'data': data})
    else:
        raise Http404


def online_visitors(request):
    if request.method == 'POST':
        online_ips = cache.get("online_ips", [])

        if online_ips:
            online_ips = list(cache.get_many(online_ips).keys())

        vistiors = Visitor.objects.filter(ip_address__in=online_ips)
        data = []
        for v in vistiors:
            data.append({'nickname': v.nickname + ip_protect(v.ip_address) + '[' + v.city + ']',
                         'date_time': utc2local(v.date_time).strftime('%H:%M')})

        return JsonResponse({'data': data})
    else:
        raise Http404


def visit_count(request):
    if request.method == 'POST':
        pv_count = BrowseRecord.objects.count()
        uv_count = Visitor.objects.count()
        return JsonResponse({'pv': pv_count, 'uv': uv_count})
    else:
        raise Http404
